﻿using Godot;
using System;
using System.Collections.Generic;

public class TargetsSelectControl : BaseTargetsControl
{
    private Action _refresh;
    private Control _root;
    private Vector2 _start;
    private Vector2 _end;
    private OperatorModeType _operatorMode;
    private List<UIElement> _targets;
    public OperatorModeType OperatorMode => _operatorMode;
    public TargetsSelectControl(Action refresh, Control root, ITargetsData data) : base(data)
    {
        _refresh = refresh;
        _root = root;
        _targets = new List<UIElement>();
        _start = Vector2.Zero;
        _end = Vector2.Zero;
        _operatorMode = OperatorModeType.SingleSelect;
    }
    public void ApplySelect()
    {
        Data.SetTargets(_targets);
        _targets.Clear();
        _refresh();
    }
    public void Begin(InputEventMouse e)
    {
        GD.Print("BeginMultiple");
        SetSingle(e);
        _operatorMode = OperatorModeType.MultipleSelect;
        _refresh();
    }
    public void End(InputEventMouse e)
    {
        GD.Print("EndMultiple");
        _operatorMode = OperatorModeType.SingleSelect;
        if (PreselectRect.Size == Vector2.Zero)
            SetSingle(e);
        ApplySelect();
    }
    public void OnMouseEvent(InputEventMouse e)
    {
        switch (_operatorMode)
        {
            case OperatorModeType.SingleSelect:
                SetSingle(e);
                break;
            case OperatorModeType.MultipleSelect:
                SetMultiple(e);
                break;
                /*case OperatorModeType.Move:
                    SetMove(e);
                    break;*/
        }
    }
    private void SetSingle(InputEventMouse e)
    {
        _start = e.Position;
        _end = e.Position;
        _targets.Clear();
        var hit = false;
        ForeachChild<UIElement>(_root, PreselectRect, (rect, ui) =>
        {
            if (hit) ui.Reset();
            else
            {
                if (ui.OnHandleSelectRect(rect))
                {
                    hit = true;
                    _targets.Add(ui);
                }
            }
        });
        _refresh();
    }
    private void SetMultiple(InputEventMouse e)
    {
        _end = e.Position;
        _targets.Clear();
        ForeachChild<UIElement>(_root, PreselectRect, (rect, ui) =>
        {
            if (ui.OnHandleSelectRect(rect))
            {
                _targets.Add(ui);
            }
        });
        _refresh();
    }
    public Rect2 PreselectRect => RectUtil.FromMinMax(_start, _end);
    private void ForeachChild<T>(Control node, Rect2 rect, Action<Rect2, T> callback)
    {
        rect.Position -= node.RectPosition;
        rect.Position /= node.RectScale.x;
        rect.Size /= node.RectScale.x;
        for (var i = node.GetChildCount() - 1; i >= 0; i--)
        {
            ForeachChild(node.GetChild<Control>(i), rect, callback);
        }
        if (node is T t)
            callback(rect, t);
    }
}
